/**
 * 
 */
package org.xnat.xnatfs.webdav;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * @author blezek
 * 
 */
public class Experiment extends VirtualDirectory {
  private final static Logger logger = Logger.getLogger ( Experiment.class );

  private final static String ASSESSORS = "Assessors";
  private final static String RECONSTRUCTIONS = "Reconstructions";
  private final static String DEFAULT_QUALITY = "usable";
  private String quality;
  private List<String> qualityDirectories = new ArrayList<String> ();

  // private HashMap<String, String> mScanLookup = new HashMap<String, String> ();

  public Experiment ( XNATFS x, String path, String name, String url ) {
    super ( x, path, name, url );
    elementURL = mURL + "scans?format=json";
    childKeys.add ( "ID" );
    childKeys.add ( "id" );
    verboseDirectoryName = "Scans";
    extraChildren.add ( ASSESSORS );
    extraChildren.add ( RECONSTRUCTIONS );
    extraChildren.add ( RESOURCES );
    quality = "usable";
  }

  public String getQuality () {
    return quality;
  }

  public void setQuality ( String s ) {
    quality = s;
  }

  @Override
  protected ChildEntry getChildEntryFromJSON ( JSONObject obj ) throws JSONException {
    for ( String k : childKeys ) {
      logger.debug ( "Checking " + k );
      if ( obj.has ( "quality" ) && obj.getString ( "quality" ).equals ( quality ) ) {
        if ( obj.has ( k ) && obj.has ( "type" ) ) {

          String key = obj.getString ( k );
          String name = obj.getString ( k ) + "-" + cleanScanType ( obj.getString ( "type" ) );
          ChildEntry ce = new ChildEntry ();
          ce.key = name;
          ce.name = name;
          ce.id = key;
          logger.debug ( "getChildEntryFromJSON: put " + name + ": " + name );
          return ce;
        }
      } else {
        // Add to our child list
        if ( quality.equals ( DEFAULT_QUALITY ) ) {
          String q = obj.getString ( "quality" );
          if ( q != null && !qualityDirectories.contains ( q ) ) {
            qualityDirectories.add ( q );
            return new ChildEntry ( q );
          }
        }
        return null;
      }
    }
    return super.getChildEntryFromJSON ( obj );
  }

  @Override
  public VirtualResource child ( String childName ) {
    if ( xnatfs.useVerboseFolders () && !verboseDirectory ) {
      // this object is not the verbose folder, but we must create one.
      if ( childName.equals ( verboseDirectoryName ) ) {
        VirtualDirectory d = new Experiment ( xnatfs, absolutePath, verboseDirectoryName, mURL );
        d.setVerboseDirectory ( true );
        return d;
      }
      if ( childName.equals ( ASSESSORS ) || childName.equals ( RECONSTRUCTIONS ) ) {
        VirtualDirectory d = new Scan ( xnatfs, absolutePath, childName, mURL + childName.toLowerCase () + "/" );
        return d;

      }
      if ( childName.equals ( RESOURCES ) ) {
        VirtualDirectory d = new Resources ( xnatfs, absolutePath, childName, mURL );
        d.setVerboseDirectory ( true );
        return d;
      }
    }

    logger.debug ( "child: create " + childName + " in directory " + absolutePath );
    String xnatId = childName;
    try {
      getElementList ();
    } catch ( Exception e ) {
      logger.warn ( "Faield to populate lookup table", e );
    }
    // Must check quality directories first, because the directories are also stored
    // in the mChildMap.
    if ( qualityDirectories.contains ( childName ) ) {
      Experiment qd = new Experiment ( xnatfs, path, childName, mURL );
      qd.setQuality ( childName );
      qd.setVerboseDirectory ( true );
      return qd;
    }
    if ( childMap.containsKey ( childName ) ) {
      ChildEntry ce = childMap.get ( childName );
      xnatId = ce.id;
      VirtualResource scan = new Scan ( xnatfs, absolutePath, ce.name, mURL + "scans/" + xnatId + "/" );
      return scan;
    }
    return null;
  }

  private String cleanScanType ( String original ) {
    if ( original == null || original.length () == 0 ) {
      return null;
    }
    return original.replaceAll ( "[\\W]", "_" );
  }
}
